package com.ysd.lis.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.lis.entity.WkCalcDatabase;
import com.ysd.lis.entity.WkCalcElement;
import com.ysd.lis.entity.WkCalcResultSql;
import com.ysd.lis.entity.*;
import com.ysd.lis.mapper.WkCalcResultSqlMapper;
import com.ysd.lis.request.BuildResultDataParams;
import com.ysd.lis.request.WkCalcResultSqlDto;
import com.ysd.lis.service.WkCalcResultService;
import com.ysd.lis.service.WkCalcResultSqlService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 核算结果-Sql记录表 服务实现类
 * </p>
 *
 * @author LiuQi
 * @since 2024-04-25
 */
@Service
public class WkCalcResultSqlServiceImpl extends ServiceImpl<WkCalcResultSqlMapper, WkCalcResultSql> implements WkCalcResultSqlService {

    @Autowired
    WkCalcResultSqlMapper wkCalcResultSqlMapper;

    @Autowired
    WkCalcResultService wkCalcResultService;

    /**
     * 查询sql表中的数据， 执行sql
     */
    @Override
    public void findCalcResultList(BuildResultDataParams buildResultDataParams) {
        MPJLambdaWrapper<WkCalcResultSql> wkCalcResultSqlDtoMPJLambdaWrapper = JoinWrappers.lambda(WkCalcResultSql.class)
                .selectAll(WkCalcResultSql.class)
                .selectAs(WkCalcDatabase::getDatabaseName, WkCalcResultSqlDto::getDatabaseName)
                .selectAs(WkCalcDatabase::getDatabaseCode, WkCalcResultSqlDto::getDatabaseCode)
                .selectAs(WkCalcDatabase::getDatabaseType, WkCalcResultSqlDto::getDatabaseType)
                .selectAs(WkCalcDatabase::getHost, WkCalcResultSqlDto::getHost)
                .selectAs(WkCalcDatabase::getPort, WkCalcResultSqlDto::getPort)
                .selectAs(WkCalcDatabase::getUsername, WkCalcResultSqlDto::getDataUsername)
                .selectAs(WkCalcDatabase::getPassword, WkCalcResultSqlDto::getPassword)
                .selectAs(WkCalcDatabase::getDbName, WkCalcResultSqlDto::getDbName)
                .leftJoin(WkCalcElement.class, WkCalcElement::getId, WkCalcResultSql::getElementId)
                .leftJoin(WkCalcDatabase.class, WkCalcDatabase::getId, WkCalcElement::getDatabaseId)
                .between(WkCalcResultSql::getStartDate, DateUtil.beginOfDay(DateUtil.parse(buildResultDataParams.getDates().get(0), "yyyy-MM-dd").toJdkDate()), DateUtil.endOfDay(DateUtil.parse(buildResultDataParams.getDates().get(1), "yyyy-MM-dd").toJdkDate()));
        List<WkCalcResultSqlDto> wkCalcResultSqlDtos = wkCalcResultSqlMapper.selectJoinList(WkCalcResultSqlDto.class, wkCalcResultSqlDtoMPJLambdaWrapper);
        List<WkCalcResult> calcResults = new ArrayList<>();
        Map<String, List<WkCalcResultSqlDto>> collect = wkCalcResultSqlDtos.stream().collect(Collectors.groupingBy(dto -> dto.getFormulaId() + "+" + dto.getUserId() + dto.getStartDate()));
        collect.forEach((key, value) -> {
            calcResults.add(buildCalcResult(value, buildResultDataParams.getBatchId(), buildResultDataParams.getBatchCode()));
        });
        boolean b = wkCalcResultService.saveBatch(calcResults);
    }

    public WkCalcResult buildCalcResult(List<WkCalcResultSqlDto> resultSqlDtos, String batchId, String batchCode) {
        WkCalcResult wkCalcResult = new WkCalcResult();
        wkCalcResult.setFormulaId(resultSqlDtos.get(0).getFormulaId());
        wkCalcResult.setFormulaCode(resultSqlDtos.get(0).getFormulaCode());
        wkCalcResult.setFormulaName(resultSqlDtos.get(0).getFormulaName());
        wkCalcResult.setUserCode(resultSqlDtos.get(0).getUserCode());
        wkCalcResult.setUserName(resultSqlDtos.get(0).getUserName());
        String formula = resultSqlDtos.get(0).getFormula();
        for (WkCalcResultSqlDto calcResultSqlDto : resultSqlDtos) {
            formula = formula.replace("#" + calcResultSqlDto.getElementId() + "#", calcResultSqlDto.getResult() + "");
        }
        Expression expression = new ExpressionBuilder(formula).build();
        double result1 = expression.evaluate();
        BigDecimal round = NumberUtil.round(result1, 4);
        wkCalcResult.setResultValue(round.doubleValue());
        wkCalcResult.setStartDate(resultSqlDtos.get(0).getStartDate());
        wkCalcResult.setEndDate(resultSqlDtos.get(0).getEndDate());
        wkCalcResult.setBatchId(batchId);
        wkCalcResult.setBatchCode(batchCode);
        return wkCalcResult;
    }
}
